home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v10n22.arc / LCVT.ASM < prev    next >
Assembly Source File  |  1991-12-08  |  9KB  |  223 lines

  1.         title   LCVT --- Convert 32-bit signed integer to formatted ASCII
  2.         page    55,132
  3.  
  4. ; LCVT.ASM --- Convert signed long (32-bit) integer
  5. ;              to formatted ASCII decimal string
  6. ;
  7. ; Copyright (C) 1989 Ray Duncan
  8. ;
  9. ; Call with:    BH    = decimal places
  10. ;               BL    = field width
  11. ;               CH    = conversion flags
  12. ;                       bit meaning
  13. ;                        7  = 0 if left justify
  14. ;                             1 if right justify
  15. ;                        6  = 0 fill field with * 
  16. ;                               if number too large
  17. ;                             1 truncate to fit
  18. ;                        5  = 0 prefix with - only
  19. ;                             1 prefix with + or -
  20. ;                        4  = 0 pad with blanks
  21. ;                             1 pad with char in CL
  22. ;                       0-3 = reserved
  23. ;               CL    = pad character 
  24. ;                       (if bit 4 of CH is set)
  25. ;               DX:AX = 32-bit signed integer
  26. ;               DS:SI = buffer to receive string
  27. ;
  28. ; Returns:      if successful,
  29. ;               Carry = clear
  30. ;               DS:SI = formatted string
  31. ;               AX    = output field length
  32. ;
  33. ;               if error (number too large,
  34. ;               and bit 6 of CH was not set),
  35. ;               Carry = set 
  36. ;               and output buffer filled with '*'
  37. ;
  38. ; Destroys:     DX
  39. ;
  40. ; At least one significant digit is always stored. Calling this 
  41. ; function with field width = zero results in an error return.
  42.  
  43. DGROUP  group   _DATA
  44.  
  45. flags   equ     [bp-1]                  ; formatting flags
  46. fpad    equ     [bp-2]                  ; pad character, if any
  47. fdecpl  equ     [bp-3]                  ; decimal places in output
  48. fwidth  equ     [bp-4]                  ; width of output field
  49. fseg    equ     [bp-6]                  ; segment of output field
  50. foffs   equ     [bp-8]                  ; offset of output field
  51. fsign   equ     [bp-10]                 ; sign of original number
  52.  
  53. _DATA   segment word public 'DATA'
  54.  
  55. buflen  equ     16                      ; length of working buffers
  56.  
  57. buf1    db      buflen dup (?)          ; LTOA builds string here
  58. buf2    db      buflen dup (?)          ; formatted string built here
  59.  
  60. _DATA   ends
  61.  
  62.  
  63. _TEXT   segment word public 'CODE'
  64.  
  65.         assume  cs:_TEXT
  66.  
  67.         extrn   LTOA:near
  68.  
  69.         public  lcvt            
  70. lcvt    proc    near            
  71.  
  72.         push    es                      ; save registers
  73.         push    di
  74.         push    bp
  75.         push    cx
  76.         push    bx
  77.  
  78.         mov     bp,sp                   ; set up local variables
  79.         sub     sp,10
  80.         mov     fpad,cx                 ; save flags and pad char.
  81.         mov     fwidth,bx               ; save width and dec. places
  82.         mov     fseg,ds                 ; save output field segment
  83.         mov     foffs,si                ; save output field offset
  84.         mov     fsign,dx                ; save sign of number
  85.  
  86.         or      bl,bl                   ; is output width zero?
  87.         jnz     lcvt01                  ; no, proceed
  88.         jmp     lcvt15                  ; error if width = zero
  89.  
  90. lcvt01: cmp     bh,(buflen+2)           ; too many decimal places?
  91.         jbe     lcvt02                  ; no, proceed
  92.         jmp     lcvt14                  ; error if buffer too small
  93.  
  94. lcvt02: or      dx,dx                   ; test sign of number...
  95.         jns     lcvt03                  ; jump if number positive
  96.  
  97.         neg     dx                      ; negative, take abs. value
  98.         neg     ax                      ; of number so we can control
  99.         sbb     dx,0                    ; sign placement
  100.  
  101. lcvt03: mov     cx,10                   ; use decimal base
  102.         mov     si,DGROUP               ; set DS:SI = local buffer
  103.         mov     ds,si
  104.         mov     si,offset DGROUP:buf1
  105.  
  106.         call    LTOA                    ; convert DX:AX to ASCII
  107.                                         ; returns DS:SI -> string,
  108.                                         ;         AX = length
  109.  
  110.                                         ; now format the string...
  111.         add     si,ax                   ; point to end of string
  112.         dec     si                      ; returned by LTOA
  113.         mov     cx,ax                   ; let CX = string length
  114.  
  115.         push    ds                      ; point to end of buffer
  116.         pop     es                      ; for formatted string
  117.         mov     di,offset DGROUP:buf2+buflen-1
  118.  
  119.         std                             ; prepare for backwards move
  120.         xor     bx,bx                   ; init. places counter
  121.  
  122. lcvt04: movsb                           ; transfer one char.
  123.         inc     bx                      ; count characters
  124.         cmp     bl,fdecpl               ; need decimal point now?
  125.         jne     lcvt05                  ; no, jump
  126.         mov     al,'.'                  ; yes, store it
  127.         stosb
  128.  
  129. lcvt05: loop    lcvt04                  ; until all chars. transferred
  130.         cmp     bl,fdecpl               ; decimal taken care of?
  131.         ja      lcvt08                  ; yes, jump
  132.         je      lcvt07                  ; well, partially...
  133.         
  134. lcvt06:                                 ; no, need decimal point
  135.         mov     al,'0'                  ; store zeros up to 
  136.         stosb                           ; decimal point
  137.         inc     bx
  138.         cmp     bl,fdecpl
  139.         jne     lcvt06
  140.         mov     al,'.'                  ; store decimal point
  141.         stosb
  142.  
  143. lcvt07: mov     al,'0'                  ; force leading zero
  144.         stosb
  145.  
  146. lcvt08: test    word ptr fsign,-1       ; was number negative?
  147.         jns     lcvt09                  ; no, jump
  148.         mov     al,'-'                  ; yes, store '-' sign
  149.         stosb
  150.         jmp     lcvt10
  151.  
  152. lcvt09: test    byte ptr flags,20h      ; is + sign needed?
  153.         jz      lcvt10                  ; no, jump
  154.         mov     al,'+'                  ; yes, store '+' sign
  155.         stosb
  156.  
  157. lcvt10: cld                             ; string now formatted
  158.                                         ; with dec. point & sign
  159.         mov     si,di                   ; copy address
  160.         inc     si                      ; calc. length of string
  161.         mov     ax,offset DGROUP:buf2+buflen
  162.         sub     ax,si                   ; now AX = length
  163.         mov     es,fseg                 ; set ES:DI = address and
  164.         mov     di,foffs                ; CX = length of user's 
  165.         mov     cl,fwidth               ; output buffer
  166.         xor     ch,ch
  167.         jcxz    lcvt15                  ; return error if width = zero
  168.         cmp     cx,ax                   ; string too big for field?
  169.         jae     lcvt11                  ; no, jump
  170.         test    byte ptr flags,40h      ; OK to truncate string?
  171.         jz      lcvt14                  ; no, return error
  172.         mov     ax,cx                   ; truncate formatted length
  173.  
  174. lcvt11: push    ax                      ; save formatted length
  175.         mov     al,' '                  ; default pad char = blank
  176.         test    byte ptr flags,10h      ; test special padding flag
  177.         jz      lcvt12                  ; jump if use ASCII blank
  178.         mov     al,fpad                 ; else use special char
  179.  
  180. lcvt12: rep stosb                       ; flood field with pad character
  181.         mov     di,foffs                ; restore output buffer address
  182.         pop     cx                      ; length of formatted string
  183.         test    byte ptr flags,80h      ; left or right justify?
  184.         jz      lcvt13                  ; jump if left justify
  185.         mov     al,fwidth               ; right justify, length of
  186.         xor     ah,ah                   ; user's output buffer
  187.         sub     ax,cx                   ; - formatted string length
  188.         add     di,ax                   ; = offset into output field
  189.  
  190. lcvt13: rep movsb                       ; transfer formatted string
  191.         clc                             ; success signal: clear Carry 
  192.         jmp     lcvt16                  ; go clean up and exit
  193.  
  194. lcvt14:                                 ; error encountered, fill
  195.                                         ; output field with '*' chars.
  196.         mov     es,fseg                 ; ES:DI -> output field
  197.         mov     di,foffs
  198.         mov     cl,fwidth               ; CX = output field length
  199.         xor     ch,ch           
  200.         mov     al,'*'                  ; character = asterisk 
  201.         rep stosb                       ; flood the output buffer
  202.  
  203. lcvt15: stc                             ; error signal: set Carry 
  204.  
  205. lcvt16: mov     ds,fseg                 ; return DS:SI = address
  206.         mov     si,foffs                ; of output field
  207.         mov     al,fwidth               ; AX = output field width
  208.         mov     ah,0                    ; (protect carry flag)
  209.         mov     sp,bp                   ; discard local variables
  210.  
  211.         pop     bx                      ; restore registers
  212.         pop     cx
  213.         pop     bp
  214.         pop     di
  215.         pop     es
  216.         ret                             ; back to caller
  217.  
  218. lcvt    endp
  219.  
  220. _TEXT   ends
  221.  
  222.         end
  223.